package com.zjs.jsp.axd.web;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zjs.jsp.axd.config.StatusMapConfig;
import com.zjs.jsp.axd.model.AxdOrderStatus;
import com.zjs.jsp.axd.model.StatusParam;
import com.zjs.jsp.axd.service.AxdApiService;
import com.zjs.jsp.domain.stats.OrderStatus;
import com.zjs.jsp.domain.stats.StatusRoot;
import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.lang.reflect.Field;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.HashMap;
import java.util.Map;

/**
 * @author 李文
 * @create 2018-07-24 16:56
 **/
@RestController
public class EdiOrderStatusApiController
{

    private static final Logger LOG = LoggerFactory.getLogger(EdiOrderStatusApiController.class);

    @Autowired
    ObjectMapper objectMapper;
    @Autowired
    StatusMapConfig smc;
    @Autowired
    AxdApiService axdService;

    @PostMapping("/OrderStatus")
    public StatusRoot statusApi(@RequestBody OrderStatus os) {

        LOG.info("{} 接受到的数据是 {} ", os.getId(), os);
        StatusRoot root = new StatusRoot();
        root.setStatus("N");

        try {
            // String ar, String cr, String ec, Integer os, String poc,
            // String rc, BigDecimal lat,
            // BigDecimal lng, String rm, String rn, Long tsu

            AxdOrderStatus axd = new AxdOrderStatus(os.getAr(), os.getCr(), os.getEc(),
                    os.getOs(), os.getPoc(), os.getCr(), os.getLat(),
                    os.getLng(), os.getRm(), os.getRn(), os.getTsu());

            axd = getOrderStatus(axd);
            if (pushMessageHandle(axd)) {
                root.setStatus("Y");
            }
        } catch (Exception e) {
            root.setStatus(e.getMessage());
        }
        LOG.info(" {}  响应的数据是 {}", os.getId(), root);
        return root;
    }

    private AxdOrderStatus getOrderStatus(AxdOrderStatus os) {
        // 60状态是异常状态 特殊处理
        if ("60".equals(os.getOs().toString()) && !StringUtils.isEmpty(os.getAr())) {

            // 通过MQ的异常编码获取 对应安鲜达 的状态码
            os.setOs(smc.getException().get(os.getAr()));
            // 异常匹配
            // MQ异常编码 就是给安鲜达的异常编码
            //os.setEc(mm.getExcpCode());
            os.setAr(smc.getCodeException().get(os.getAr()));
            if ("3401".equals(os.getAr()) || "3501".equals(os.getAr()) || "1104".equals(os.getAr())) {
                os.setOs(80);
            }
            os.setEc(smc.getaxdExcepCodeMap().get(os.getAr()));
            os.setAr(smc.getCodeException().get(os.getAr()));
        } else {
            // 不是异常情况下 进行正常匹配
            os.setOs(smc.getStatusMapInfo().get(os.getOs().toString()));
        }
        return os;
    }

    private boolean pushMessageHandle(AxdOrderStatus jspstatus) throws JsonProcessingException {
        String[] fieldstr = new String[]{"abnormal_reason", "cancel_reason", "error_code", "id", "order_status",
                "partner_order_code", "rider_code", "rider_lat", "rider_lng", "rider_mobile", "rider_name", "su",
                "time_status_update"};

        if (jspstatus != null) {
            // 安鲜达不需要这个值去掉之后序列化不包含此值

            jspstatus.setSu(null);
            long timestampt = LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
            LOG.info("{} 推送时间戳 {}", jspstatus.getId(), timestampt);
            String json = objectMapper.writeValueAsString(jspstatus);
            LOG.info(" {} 推送报文 {}", jspstatus.getId(), json);

            // 加密字符串生成

            // 属性字段室友排序的 java 不是net 还要自己写算法 安鲜达就是他妈脑残
            // 手动排序了

            StringBuilder sbfield = new StringBuilder();
            Field[] field = jspstatus.getClass().getDeclaredFields();

            Map<String, Object> ncmap = new HashMap<>();
            for (Field aa : field) {
                try {
                    aa.setAccessible(true);
                    ncmap.put(aa.getName(), aa.get(jspstatus));
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            for (String aFieldstr : fieldstr) {
                if (!"id".equals(aFieldstr) && !"su".equals(aFieldstr)) {
                    sbfield.append(aFieldstr);
                    if (ncmap.get(fieldmap.get(aFieldstr)) != null) {
                        sbfield.append(ncmap.get(fieldmap.get(aFieldstr)));
                    }
                }
            }
            String sig = getsig(sbfield.toString());
            LOG.info(" {} 报文 签名:{}", jspstatus.getId(), sig);
            StatusParam sp = new StatusParam(smc.getAppId(), timestampt, json, sig);
            //String request = objectMapper.writeValueAsString(sp);
            //String returnstr = sendPost(smc.getUrl(), request);
            String returnstr = axdService.send(sp);
            LOG.info(" {} POST请求体{},推送返回结果:{}", jspstatus.getId(), sp, returnstr);

            return returnstr.contains("200");
        }

        return false;

    }

    static Map<String, String> fieldmap = new HashMap<String, String>();

    static {
        fieldmap.put("abnormal_reason", "ar");
        fieldmap.put("cancel_reason", "cr");
        fieldmap.put("error_code", "ec");
        fieldmap.put("order_status", "os");
        fieldmap.put("partner_order_code", "poc");
        fieldmap.put("rider_code", "rc");
        fieldmap.put("rider_lat", "lat");
        fieldmap.put("rider_lng", "lng");
        fieldmap.put("rider_mobile", "rm");
        fieldmap.put("rider_name", "rn");
        fieldmap.put("time_status_update", "tsu");

    }


    private String getsig(String json) {
        String my = smc.getSecretKey();

        StringBuilder sb = new StringBuilder();
        sb.append(my);
        // sb.append("code200data");
        sb.append(json);
        // sb.append("msg成功");
        sb.append(my);
        String sigstr = sb.toString();
        LOG.info("待加密字符串 :{}", sigstr);
        @SuppressWarnings("deprecation")
        String shaHex = DigestUtils.shaHex(sigstr);
        return shaHex.toUpperCase();
    }
}
